package com.xc.quickstart.common.aspect;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.xc.quickstart.common.context.ApiContext;
import com.xc.quickstart.common.exception.ApiArgumentBizException;
import com.xc.quickstart.common.exception.CommonBizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.xc.quickstart.common.model.ApiResponse;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestControllerAdvice
@Slf4j
public class ExceptionControllerAdvice {

    @ExceptionHandler
    public ApiResponse handleException(Exception ex) {
        log.error("[ExceptionControllerAdvice]请求处理Exception异常,ex:{},crmTraceId:{}", ExceptionUtil.stacktraceToString(ex), ApiContext.getCrmTraceId());
        return ApiResponse.fail("系统异常");
    }

    @ExceptionHandler({CommonBizException.class})
    public ApiResponse handleCommonBizExistException(CommonBizException ex) {
        log.error("[ExceptionControllerAdvice]请求处理CommonBizException异常,msg:{},code:{},ex:{}", ex.getMsg(),ex.getCode(), ExceptionUtil.stacktraceToString(ex));
        return ApiResponse.fail(ex.getMsg());
    }

    @ExceptionHandler({ApiArgumentBizException.class})
    public ApiResponse handleApiArgumentBizExistException(ApiArgumentBizException ex) {
        log.error("[ExceptionControllerAdvice]请求处理ApiArgumentBizException异常,msg:{},code:{},ex:{}", ex.getMsg(), ex.getCode(), ExceptionUtil.stacktraceToString(ex));
        return ApiResponse.fail(String.format("参数校验异常：%s", ex.getMsg()));
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ApiResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindResult = ex.getBindingResult();
        List<ObjectError> errors = bindResult.getAllErrors();
        Map<String, Object> msgMap = new HashMap<>();

        errors.forEach(error -> {
            if (error instanceof FieldError) {
                FieldError fieldError = (FieldError) error;
                msgMap.put(StrUtil.toUnderlineCase(fieldError.getField()), fieldError.getDefaultMessage());
            } else {
                msgMap.put(StrUtil.toUnderlineCase(error.getObjectName()), error.getDefaultMessage());
            }
        });

        log.error("[ExceptionControllerAdvice]请求处理MethodArgumentNotValidException异常,msg:{},ex:{}",JSON.toJSONString(msgMap), ExceptionUtil.stacktraceToString(ex));
        return ApiResponse.fail(String.format("参数校验异常：%s", JSON.toJSONString(msgMap)));
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ApiResponse processException(ConstraintViolationException ex, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> msgMap = new HashMap<>();
        ex.getConstraintViolations().forEach(error -> {
            String message = error.getMessage();
            String path = error.getPropertyPath().toString();
            msgMap.put(StrUtil.toUnderlineCase(path), message);
        });
        log.error("[ExceptionControllerAdvice]请求处理ConstraintViolationException异常,msg:{},ex:{}",JSON.toJSONString(msgMap), ExceptionUtil.stacktraceToString(ex));
        return ApiResponse.fail(String.format("参数校验异常：%s", JSON.toJSONString(msgMap)));
    }

}
